package com.bitcarton.disso.core.interceptor;

import com.bitcarton.disso.annotation.Handler;
import com.bitcarton.disso.annotation.Login;
import com.bitcarton.disso.config.Config;
import com.bitcarton.disso.helper.SsoLoginHelper;
import com.bitcarton.disso.utils.CookieUtil;
import com.bitcarton.disso.utils.SsoClientUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author wwd
 */
public class SsoClientInterceptor implements HandlerInterceptor {
    private static Logger logger = LoggerFactory.getLogger(SsoClientInterceptor.class);
    /**
     * 统一认证中心服务地址 Service address of unified certification authority
     */
    private String ssoServerUrl;

    /**
     * 将要重定向的路径 The path to be redirected
     */
    private String ssoClientUrl;

    /**
     * 退出登录地址 Exit login address
     */
    private String ssoLogoutPath;
    /**
     * 微服务同归注册中心的服务名称
     */
    private String ssoApplicationName;

    public SsoClientInterceptor(Environment environment) {
        ssoServerUrl = environment.getProperty("disso.serve.url");
        ssoClientUrl = environment.getProperty("disso.client.url");
        ssoLogoutPath = environment.getProperty("disso.logout.path");
        ssoApplicationName = environment.getProperty("disso.serve.application.name");
    }


    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            Login login = method.getAnnotation(Login.class);
            if (null != login && login.handler() == Handler.PASS) {
                //请求直接放行
                return true;
            }
        }
        String servletPath = req.getServletPath();
        if ("/v1/sso/checkLogin".equals(servletPath)||servletPath.contains("/sso/checkLogin")){
            return true;
        }
        if ("/error".equals(servletPath)){
            //报错
            Object redirectUrl = req.getAttribute("redirectUrl");
            if (null!=redirectUrl){
                resp.sendRedirect(redirectUrl.toString());
            }
            return true;
        }
         if (servletPath.contains("/sso/login")){
            String token = CookieUtil.getValue(req, Config.SSO_TOKEN);
            if (StringUtils.isBlank(token)) {
                token = req.getParameter(Config.SSO_TOKEN);
            }
            if (StringUtils.isNoneBlank(token)) {
                try {
                    boolean isVerify = SsoLoginHelper.verifyToken(token);
                    if (isVerify) {
                        //移除老的cookie
                        CookieUtil.remove(req, resp, Config.SSO_TOKEN);
                        CookieUtil.setCookie(resp, Config.SSO_TOKEN, token, Integer.MAX_VALUE, Config.COOKIE_PATH, true);
                        req.setAttribute("isLogin",true);
                    } else {
                        //cookie验证不通过 为过期cookie清除掉
                        CookieUtil.remove(req, resp, Config.SSO_TOKEN);
                    }
                } catch (Exception e) {
                    logger.error("verifyToken error", e);
                }
            }
            return true;
        }
        if (StringUtils.isNotBlank(ssoLogoutPath) && ssoLogoutPath.equals(servletPath)) {
            String logoutPageUrl = ssoServerUrl.concat(Config.SSO_LOGOUT);
            CookieUtil.remove(req, resp, Config.SSO_TOKEN);
            resp.sendRedirect(logoutPageUrl);
            return false;
        }
        String token = CookieUtil.getValue(req, Config.SSO_TOKEN);
        if (StringUtils.isBlank(token)) {
            token = req.getParameter(Config.SSO_TOKEN);
        }
        if (StringUtils.isNoneBlank(token)) {
            try {
                boolean isVerify = SsoLoginHelper.verifyToken(token);
                if (isVerify) {
                    //移除老的cookie
                    CookieUtil.remove(req, resp, Config.SSO_TOKEN);
                    CookieUtil.setCookie(resp, Config.SSO_TOKEN, token, Integer.MAX_VALUE, Config.COOKIE_PATH, true);
                    return true;
                } else {
                    //cookie验证不通过 为过期cookie清除掉
                    CookieUtil.remove(req, resp, Config.SSO_TOKEN);
                }
            } catch (Exception e) {
                logger.error("verifyToken error", e);
            }
        }

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            ResponseBody methodAnnotation = handlerMethod.getMethodAnnotation(ResponseBody.class);
            if (null!=methodAnnotation){

                SsoClientUtil.redirectToSsoLoginUrl(req, resp, ssoClientUrl, ssoServerUrl);
                return false;
            }
            RestController annotation = handlerMethod.getBean().getClass().getAnnotation(RestController.class);
            if (annotation!=null){
                SsoClientUtil.redirectToSsoLoginUrl(req, resp, ssoClientUrl, ssoServerUrl);
                return false;
            }
        }

        SsoClientUtil.redirectToSsoUrl(req, resp, ssoClientUrl, ssoServerUrl,ssoApplicationName);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }
}
